#include <MLlib/MLLib.h>
#include <FreeTypeGX.h>
#include <network.h>
#include <string>
#include <vector>
#include <pthread.h>


#include "fyl_network.h"

#include "trebuchet_ttf.h"
#include "main_bg_png.h"
#include "button_minus_png.h"
#include "button_plus_png.h"
#include "button_one_png.h"
#include "button_a_png.h"
#include "button_home_png.h"

using namespace std;

void executeFMLRequest(char *m, vector<string> *stories);
void *executeFMLRequestA(void *req);

void drawText(FreeTypeGX *ftgx, int px, int py, int width, int height,
	GXColor color, char *text);

vector<string> *parseContent(string *content);
vector<string> *parseHTML(string *html);
vector<string> *stories;

bool working = false;

int main(int argc, char **argv)
{

	// Initialize whatever MLLib components we need.
	ML_Init();

	// Initialize the FreeTypeGX library with the Trebuchet font.
	FreeTypeGX *ftgx = new FreeTypeGX();
	ftgx->loadFont(trebuchet_ttf, trebuchet_ttf_size, 18);

	// Initialize the Wii network library.
	string msg = "Initializing network...";
	while (net_init() < 0)
	{

		drawText(ftgx, 10, 40, 400, 100, (GXColor) {255, 255, 255, 255},
			(char*) msg.c_str());
		msg.append(".");

		ML_Refresh();

	}

	// Load our application graphics.
	ML_Image *main_bg_data = new ML_Image();
	ML_Sprite *main_bg = new ML_Sprite();
	ML_LoadSpriteFromBuffer(main_bg_data, main_bg, main_bg_png, 0, 20);

	ML_Image *button_minus_data = new ML_Image();
	ML_Sprite *button_minus = new ML_Sprite();
	ML_LoadSpriteFromBuffer(
		button_minus_data, button_minus, button_minus_png, 20, 210);

	ML_Image *button_plus_data = new ML_Image();
	ML_Sprite *button_plus = new ML_Sprite();
	ML_LoadSpriteFromBuffer(
		button_plus_data, button_plus, button_plus_png, 540, 210);

	ML_Image *button_one_data = new ML_Image();
	ML_Sprite *button_one = new ML_Sprite();
	ML_LoadSpriteFromBuffer(button_one_data, button_one, button_one_png,
		70, 390);

	ML_Image *button_a_data = new ML_Image();
	ML_Sprite *button_a = new ML_Sprite();
	ML_LoadSpriteFromBuffer(button_a_data, button_a, button_a_png, 320, 390);

	ML_Image *button_home_data = new ML_Image();
	ML_Sprite *button_home = new ML_Sprite();
	ML_LoadSpriteFromBuffer(button_home_data, button_home, button_home_png,
		480, 50);

	// Application variables.
	bool appActive = true;
	stories = new vector<string>;

	string news =
		"FMyLife Reader for the Wii\n"
		"version 0.2.4\n\n"
		"Programming, Graphics by rosch\n"
		"Tested by Athenon, Yossi from #WiiHelp on EfNET\n\n"
		"Up/Down - Select FML type\n"
		"A - Get FMLs";

	stories->push_back(news);

	u32 index = 0, page = 0, menu_index = 0;
	char buffer[256];

	vector<string> menu_items;
	menu_items.push_back("Latest FMLs (%i)");
	menu_items.push_back("Random FMLs");
	menu_items.push_back("Top FMLs");

	// Main application loop.
	while (appActive)
	{

		// Draw application graphics.
		ML_DrawSprite(main_bg);
		//ML_DrawSprite(button_one);
		//ML_DrawSprite(button_a);
		ML_DrawSprite(button_home);

		if (stories->size() > 1)
		{

			if (index > 0)
				ML_DrawSprite(button_minus);

			if (index + 1 < stories->size())
				ML_DrawSprite(button_plus);

		}

		// Draw the current story text.
		drawText(ftgx, 110, 170, 350, 200, (GXColor) {0, 0, 0, 255},
			(char*) stories->at(index).c_str());

		// Draw the number of stories available.
		sprintf(buffer, "%i of %i", (index + 1), stories->size());
		if (stories->size() > 1)
		{

			drawText(ftgx, 475, 365, 325, 100, (GXColor) {0, 0, 0, 255},
				(char*) buffer);

		}

		if (working)
		{

			drawText(ftgx, 465, 345, 325, 200, (GXColor) {0x00, 0x00, 0x00, 0xFF},
				(char *) "Working...");

		}

		for (u32 i = 0; i < menu_items.size(); i++)
		{

			sprintf(buffer, menu_items.at(i).c_str(), page);

			drawText(ftgx, 75, 390 + (20 * i), 325, 100, (GXColor) {255, 255, 255, 255},
				(char*) buffer);

			if (i == menu_index)
			{

				drawText(ftgx, 55, 390 + (20 * i), 325, 100, (GXColor) {255, 255, 255, 255},
					(char*) ">>");

			}

			buffer[0] = '\0';

		}

		if (Wiimote[0].Held.Home)
		{

			appActive = false;

		} else if (Wiimote[0].Newpress.B) {



		} else if (Wiimote[0].Newpress.A && !working) {

			if (menu_index == 0)
			{

				pthread_t t0;
				sprintf(buffer, "GET http://www.fmylife.com?page=%i\n", page++);
				string *req = new string(buffer);

				pthread_create(&t0, NULL, executeFMLRequestA, (void *) req);

			} else if (menu_index == 1) {

				pthread_t t0;
				string *req = new string("GET http://www.fmylife.com/random\n");

				pthread_create(&t0, NULL, executeFMLRequestA, (void *) req);

			} else if (menu_index == 2) {

				pthread_t t0;
				string *req = new string("GET http://www.fmylife.com/tops\n");

				pthread_create(&t0, NULL, executeFMLRequestA, (void *) req);

			}

			buffer[0] = '\0';

		// Decrement the story index.
		} else if (Wiimote[0].Newpress.Minus) {

			if (index > 0)
				index--;

		// Increment the story index.
		} else if (Wiimote[0].Newpress.Plus) {

			if (index + 1 < stories->size())
				index++;

		} else if (Wiimote[0].Newpress.Up) {

			if (menu_index > 0)
				menu_index--;

		} else if (Wiimote[0].Newpress.Down) {

			if (menu_index < 2)
				menu_index++;

		}

		ML_Refresh();

	}

	// Clean up any used variables.
	stories->clear();
	delete stories;

	ML_Exit();

	return (0);

}

void *executeFMLRequestA(void *req)
{

	string *request = (string *) req;
	working = true;

	FYL_Socket *socket;
	string host("www.fmylife.com");
	u32 port = 80;

	socket = new FYL_Socket(&host, port);
	socket->write((char *) request->c_str());

	string msg = "";
	msg = socket->read();

	vector<string> *entries = parseHTML(&msg);
	stories->insert(stories->end(), entries->begin(), entries->end());

	delete entries;

	// Close the socket and delete any references.
	socket->close();
	delete socket;

	working = false;

	return (NULL);

}

void drawText(FreeTypeGX *ftgx, int px, int py, int width, int height,
	GXColor color, char *text)
{

	// Create some variables we need for line delimiting.
	wchar_t *wt = NULL;
	string *t = new string;
	int tx = 0, ty = 0, ch = 0;

	// Get the maximum height we need.
	wt = ftgx->charToWideChar((char*) "A");
	ch = ftgx->getHeight(wt);
	delete wt;

	// Iterate through each character.
	for (u32 i = 0; i < strlen(text); i++)
	{

		// Check if the current text width exceeds what we want and if the
		// current character is a space or other punctuation point, OR if we
		// have a newline.
		if (((tx > width) &&
				((text[i] == ' ') || (text[i] == '.') ||
				(i == (strlen(text) - 1)))) ||
			(text[i] == '\n'))
		{

			if (text[i] != '\n')
				t->append(1, text[i]);

			wt = ftgx->charToWideChar((char*) t->c_str());
			ftgx->drawText(px, py + ty, wt, color);

			tx = 0;
			ty += (ch + 5);

			t->clear();
			delete [] wt;

		// Otherwise, append the character to the current text.
		} else {

			t->append(1, text[i]);

			wt = ftgx->charToWideChar((char*) t->c_str());
			tx = ftgx->getWidth(wt);

			delete [] wt;

		}

	}

	// If there are remaining characters in our text, print them out.
	if (t->size() > 0)
	{

		wt = ftgx->charToWideChar((char*) t->c_str());
		ftgx->drawText(px, py + ty, wt, color);

		t->clear();
		delete [] wt;

	}

	// Clean-up created variables.
	delete t;

}

vector<string> *parseHTML(string *html)
{

	vector<string> *items = new vector<string>;

	string sx = " | All time";
	string s0 = "<div class=\"post\" ";
	string s1 = "<div class=\"date\">";

	u32 nx = html->find(sx);

	if (nx == string::npos)
		nx = 0;

	u32 n0 = html->find(s0, nx);
	u32 n1 = html->find(s1, n0);

	while ((n0 != string::npos) && (n1 != string::npos))
	{

		string s3 = html->substr(n0, n1 - n0);
		string s4 = "";

		bool tag = false;

		for (u32 i = 0; i < s3.size(); i++)
		{

			if (s3[i] == '<')
				tag = true;
			else if (s3[i] == '>')
				tag = false;
			else
			{
				if (!tag)
					s4.push_back(s3.at(i));
			}

		}

		n0 = html->find(s0, n1);
		n1 = html->find(s1, n0);

		items->push_back(s4);

	}

	return (items);

}
